using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Gumps;
using Server.Network;


namespace Server.Items
{
	public class CloneItem : Item
	{
		private Item m_ToClone;
		private Mobile m_Cloner;

		public Item ToClone
		{
			get{ return m_ToClone; }
			set{ m_ToClone = value; InvalidateProperties(); }
		}

		public Mobile Cloner
		{
			get{ return m_Cloner; }
			set{ m_Cloner = value; InvalidateProperties(); }
		}


		[Constructable]
		public CloneItem( Mobile m, Item item ) : base( item.ItemID )
		{
			Weight = item.Weight;
			Name = item.Name;
			Hue = item.Hue;

			if ( item.Stackable )
				Stackable = true;

			Amount = item.Amount;

			m_Cloner = m;
			m_ToClone = item;
		}

		public CloneItem( Serial serial ) : base( serial )
		{
		}

		public override bool CheckItemUse( Mobile from, Item item )
		{
			return true;
		}

		public override bool IsAccessibleTo( Mobile m )
		{
			return true;
		}

		public override void AddNameProperties( ObjectPropertyList list )
		{
			if ( m_ToClone != null )
			{
				m_ToClone.AddNameProperties( list );

//				if ( m_ToClone is IUsesRemaining )
//					list.Add( 1060584, "{0}", ((IUsesRemaining)m_ToClone).UsesRemaining );	// uses remaining: ~1_val~
			}
		}

		public override void GetProperties( ObjectPropertyList list )
		{
			base.GetProperties( list );

			if ( m_ToClone != null )
				m_ToClone.GetProperties( list );
		}

		public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
		{
			base.GetContextMenuEntries( from, list );

			if ( !from.Alive || this.Deleted )
				return;

			Mobile vendor = m_ToClone.RootParent as Mobile;
			IHardsellable hs = vendor as IHardsellable;

			if ( hs == null || hs.ShopItems == null || !( hs.ShopItems.Count > 0 ) )
				return;

			TradeItem ti = VendorManager.GetTradeItem( hs, m_ToClone );

			if ( ti == null )
				return;

			BaseCreature bc = null;

			List<PetProp> pplist = new List<PetProp>();

			if ( m_ToClone is CloneMobile )
			{
				bc = ((CloneMobile)m_ToClone).ClonePet;

				VendorPetInfo vpi = new VendorPetInfo( from, bc );
				pplist = vpi.PetPropInfo;
			}

//			if ( bc != null )
//				from.SendMessage( "bc is : {0}", bc.GetType().Name );	// debug code

			if ( list != null && list.Count > 0 )
				from.SendMessage( "list count : {0}", list.Count );

			if ( ti != null )
			{
				if ( vendor is PetSeller && !hs.IsOwner( from ) && from.AccessLevel == AccessLevel.Player && from == ((CloneMobile)m_ToClone).Master )
				{
					list.Add( new ClaimPetEntry( from, ti ) );
					list.Add( new EditItemEntry( vendor, ti ) );
				}
				else if ( hs.IsOwner( from ) || from.AccessLevel > AccessLevel.Player )
				{
					list.Add( new EditItemEntry( vendor, ti ) );
					list.Add( new RemoveItemEntry( from, ti ) );
				}

				if ( m_ToClone is CloneMobile )
					list.Add( new PetInfoEntry( from, pplist ) );

				if ( ti.Price >= 0 )
					list.Add( new BuyItemEntry( vendor, ti ) );

				if ( ti.Price != 0 && hs.AllowBid )
					list.Add( new PlaceBidEntry( from, ti ) );
			}
		}

		private class ClaimPetEntry : ContextMenuEntry
		{
			private Mobile m_from;
			private TradeItem m_ti;

			public ClaimPetEntry( Mobile from, TradeItem ti ) : base( 6219 )
			{
				m_from = from;
				m_ti = ti;
			}

			public override bool NonLocalUse{ get{ return true; } }

			public override void OnClick()
			{
				Item item = (Item)m_ti.ItemObj;

				if ( item.Deleted )
					return;

				VendorManager.ToRemoveTradeItem( m_from, m_ti );
			}
		}

		private class PetInfoEntry : ContextMenuEntry
		{
			private Mobile m_from;
			private List<PetProp> m_prop = new List<PetProp>();

			public PetInfoEntry( Mobile from, List<PetProp> list ) : base( 0484 )
			{
				m_from = from;
				m_prop = list;
			}

			public override bool NonLocalUse{ get{ return true; } }

			public override void OnClick()
			{
				Owner.From.CloseGump( typeof( PetInfoGump ) );
				Owner.From.SendGump( new PetInfoGump( m_prop, 0 ) );
			}
		}

		private class PlaceBidEntry : ContextMenuEntry
		{
			private Mobile m_from;
			private TradeItem m_ti;

			public PlaceBidEntry( Mobile from, TradeItem ti ) : base( 0156 )
			{
				m_from = from;
				m_ti = ti;
			}

			public override bool NonLocalUse{ get{ return true; } }

			public override void OnClick()
			{
				Item item = (Item)m_ti.ItemObj;

				if ( item.Deleted )
					return;

				Owner.From.CloseGump( typeof( VendorBidGump ) );
				Owner.From.SendGump( new VendorBidGump( m_from, m_ti ) );
			}
		}

		// TODO: to set Enabled = from is owner
		private class RemoveItemEntry : ContextMenuEntry
		{
			private Mobile m_from;
			private TradeItem m_ti;

			public RemoveItemEntry( Mobile from, TradeItem ti ) : base( 0163 )
			{
				m_from = from;
				m_ti = ti;
			}

			public override bool NonLocalUse{ get{ return true; } }

			public override void OnClick()
			{
				Item item = (Item)m_ti.ItemObj;

				if ( item.Deleted )
					return;

				VendorManager.ToRemoveTradeItem( m_from, m_ti );
			}
		}

		private class BuyItemEntry : ContextMenuEntry
		{
			private Mobile m_vendor;
			private TradeItem m_ti;

			public BuyItemEntry( Mobile vendor, TradeItem ti ) : base( 6103 )
			{
				m_vendor = vendor;
				m_ti = ti;

				Enabled = ti.Price > 0;
			}

			public override bool NonLocalUse{ get{ return true; } }

			public override void OnClick()
			{
				Item item = (Item)m_ti.ItemObj;

				if ( m_ti.Price < 0 || item.Deleted )
					return;

				Owner.From.CloseGump( typeof( CommVendorBuyGump ) );
				Owner.From.SendGump( new CommVendorBuyGump( m_vendor, m_ti ) );
			}
		}

		private class EditItemEntry : ContextMenuEntry
		{
			private Mobile m_Vendor;
			private Item m_Item;

			public EditItemEntry( Mobile vendor, TradeItem ti ) : base( 5101 )
			{
				m_Vendor = vendor;
				m_Item = (Item)ti.ItemObj;
			}

			public override bool NonLocalUse{ get{ return true; } }

			public override void OnClick()
			{
				if ( m_Item.Deleted )
					return;

				Owner.From.CloseGump( typeof( AddTradeItemGump ) );
				Owner.From.SendGump( new AddTradeItemGump( m_Vendor, m_Item ) );
			}
		}


		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			writer.Write( (int)0 ); //version

			writer.Write( (Item) m_ToClone );
			writer.Write( (Mobile) m_Cloner );
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			int version = reader.ReadInt();

			m_ToClone = reader.ReadItem();
			m_Cloner = reader.ReadMobile();
		}
	}

	public class CloneMobile : Item
	{
		private bool m_preloaded;

		private string m_name;
		private string m_master;
		private string m_breed;
		private string m_gender;
		private string m_bonded;
		private int m_hits;
		private int m_stam;
		private int m_mana;
		private int m_str;
		private int m_dex;
		private int m_int;
		private int m_phys;
		private int m_fire;
		private int m_cold;
		private int m_pois;
		private int m_nrgy;
		private int m_dphys;
		private int m_dfire;
		private int m_dcold;
		private int m_dpois;
		private int m_dnrgy;
		private double m_wrestling;
    private double m_tactics;
    private double m_anatomy;
    private double m_poisoning;
    private double m_magery;
    private double m_evalint;
    private double m_magicresist;
    private double m_meditation;

		private Mobile m_Master;
		private Mobile m_Cloner;
		private BaseCreature m_ClonePet;

		public Mobile Master
		{
			get{ return m_Master; }
			set{ m_Master = value; InvalidateProperties(); }
		}

		public Mobile Cloner
		{
			get{ return m_Cloner; }
			set{ m_Cloner = value; InvalidateProperties(); }
		}

		public BaseCreature ClonePet
		{
			get{ return m_ClonePet; }
			set{ m_ClonePet = value; InvalidateProperties(); }
		}


		[Constructable]
		public CloneMobile( Mobile from, BaseCreature pet ) : base( LookupItemID( pet ) )
		{
			Name = pet.Name;
			Weight = 1.0;

			if ( pet.Body == 0x190 || pet.Body == 0x191 )
				Hue = 0;
			else
				Hue = pet.Hue;

			m_Cloner = from;
			m_ClonePet = pet;

			// pet.ControlMaster = null in case of Restockable vendor
			// as pet is duped for real pets and may cause crash in
			// loading m_master.Name
			m_Master = pet.ControlMaster;
			m_preloaded = false;
		}

		public CloneMobile( Serial serial ) : base( serial )
		{
		}


		private void PreLoadProps()
		{
			m_name = ClonePet.Name;
			m_master = ( m_master == null ) ? "[None]" : m_Master.Name;		// to avoid a null reference crash in case of Restockable vendor
			m_breed = CommonTools.GetFriendlyClassName( ClonePet.GetType().Name );
			m_gender = ClonePet.Female ? "Female" : "Male";
			m_bonded = ClonePet.IsBonded ? "Bonded" : "Tamed";
			m_hits = ClonePet.HitsMax;
			m_stam = ClonePet.StamMax;
			m_mana = ClonePet.ManaMax;
			m_str = ClonePet.Str;
			m_dex = ClonePet.Dex;
			m_int = ClonePet.Int;
			m_phys = ClonePet.PhysicalResistance;
			m_fire = ClonePet.FireResistance;
			m_cold = ClonePet.ColdResistance;
			m_pois = ClonePet.PoisonResistance;
			m_nrgy = ClonePet.EnergyResistance;
			m_dphys = ClonePet.PhysicalDamage;
			m_dfire = ClonePet.FireDamage;
			m_dcold = ClonePet.ColdDamage;
			m_dpois = ClonePet.PoisonDamage;
			m_dnrgy = ClonePet.EnergyDamage;
			m_wrestling = ClonePet.Skills[SkillName.Wrestling].Base;
			m_tactics = ClonePet.Skills[SkillName.Tactics].Base;
			m_anatomy = ClonePet.Skills[SkillName.Anatomy].Base;
			m_poisoning = ClonePet.Skills[SkillName.Poisoning].Base;
			m_magery = ClonePet.Skills[SkillName.Magery].Base;
			m_evalint = ClonePet.Skills[SkillName.EvalInt].Base;
			m_magicresist = ClonePet.Skills[SkillName.MagicResist].Base;
			m_meditation = ClonePet.Skills[SkillName.Meditation].Base;

			m_preloaded = true;
		}

		public override void AddNameProperties( ObjectPropertyList list )
		{
			if ( !m_preloaded )
				PreLoadProps();

			list.Add( 1041601, m_name );		// Name: ~1_NAME~
			list.Add( 1041602, m_master );		// Owner: ~1_OWNER~
			list.Add( 1060663, "Breed\t{0} Gender: {1} ({2})", m_breed, m_gender, m_bonded );
			list.Add( 1060658, "Hits\t{0}, Stamina {1}, Mana {2}", m_hits, m_stam, m_mana );		// ~1_val~: ~2_val~
			list.Add( 1060659, "Str\t{0}, Dex {1}, Int {2}", m_str, m_dex, m_int );		// ~1_val~: ~2_val~
			list.Add( 1049595 + ( ClonePet.Loyalty / 10 ) );
			list.Add( 1060660, "Resistance\tPhys {0}, Fire {1}, Cold {2}, Poison {3}, Energy {4}", m_phys, m_fire, m_cold, m_pois, m_nrgy );
			list.Add( 1060661, "Damage\tPhys {0}, Fire {1}, Cold {2}, Poison {3}, Energy {4}", m_dphys, m_dfire, m_dcold, m_dpois, m_dnrgy );
			list.Add( 1060662, "Combat\tWrestling {0}, Tactics {1}, Anatomy {2}, Poison {3}", m_wrestling, m_tactics, m_anatomy, m_poisoning );
			list.Add( 1060663, "Magic\tMagery {0}, Eval Int {1}, Magic Resist {2}, Mediation {3}", m_magery, m_evalint, m_magicresist, m_meditation );
		}


		public static int LookupItemID( BaseCreature bc )
		{
			int itemID = ShrinkTable.Lookup( bc );
			int body = (int) bc.Body;

			if ( itemID == ShrinkTable.DefaultItemID )
			{
				switch ( body )
				{
					case 276: itemID = 11669; break;	// Reptalon|Chimera
					case 277: itemID = 11670; break;	// CuSidhe
					case 278: itemID = 11671; break;	// Squirrel
					case 279: itemID = 11672; break;	// Ferret
					case 282: itemID = 11675; break;	// Parrot
					case 284: itemID = 11676; break;	// Charger Mount
				}
			}

			return itemID;
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			writer.Write( (int)0 ); //version

			writer.Write( (Mobile) m_Master );
			writer.Write( (Mobile) m_Cloner );
			writer.Write( (Mobile) m_ClonePet );
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			int version = reader.ReadInt();

			m_Master = reader.ReadMobile();
			m_Cloner = reader.ReadMobile();
			m_ClonePet = (BaseCreature)reader.ReadMobile();
		}

	}
}
